package com.baizw.cultivation.module.admin.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import com.baizw.cultivation.common.exception.GlobalException;
import com.baizw.cultivation.common.page.CustomPage;
import com.baizw.cultivation.common.properties.CultivationProperties;
import com.baizw.cultivation.common.response.ResultBean;
import com.baizw.cultivation.enums.StatusEnum;
import com.baizw.cultivation.module.admin.entity.RoleEntity;
import com.baizw.cultivation.module.admin.entity.UserEntity;
import com.baizw.cultivation.module.admin.entity.vo.LoginFormVO;
import com.baizw.cultivation.module.admin.entity.vo.UserVO;
import com.baizw.cultivation.module.admin.mapper.UserMapper;
import com.baizw.cultivation.module.admin.mapstruct.UserMapstruct;
import com.baizw.cultivation.module.admin.service.RoleService;
import com.baizw.cultivation.module.admin.service.UserService;
import com.baizw.cultivation.util.JwtUtil;
import com.baizw.cultivation.util.RedisUtil;
import com.baizw.cultivation.util.ShiroUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;

/**
 * 用户业务接口实现
 *
 * @author 白振伟
 * @version V1.0
 * @date 2020年12月29日 18:00:29
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {

    @Resource
    private UserMapstruct userMapstruct;
    @Autowired
    private RoleService roleService;
    @Autowired
    private CultivationProperties properties;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public ResultBean<Map<String, Object>> authLogin(LoginFormVO loginForm) {
        String loginName = loginForm.getLoginName();
        String passWord = loginForm.getPassword();
        String uuid = loginForm.getUuid();
        String captcha = loginForm.getCaptcha();
        UserEntity userEntity = selectByUserName(loginName);

        if (ObjectUtil.isEmpty(userEntity) || StrUtil.isBlank(userEntity.getPassword())) {
            return ResultBean.error(HttpStatus.UNAUTHORIZED.value(), "用户名或密码错误");
        }
        // 采用国密算法加密密码
        SymmetricCrypto sm4 = SmUtil.sm4(properties.sm4KeyBytes());
        String encryptHex = sm4.encryptHex(passWord);
        if (!encryptHex.equals(userEntity.getPassword())) {
            return ResultBean.error(HttpStatus.UNAUTHORIZED.value(), "用户名或密码错误");
        }
        if (!redisUtil.verifyCaptcha(uuid, captcha)) {
            return ResultBean.error(HttpStatus.UNAUTHORIZED.value(), "验证码不正确");
        }
        String sign = JwtUtil.sign(loginName, passWord);
        redisUtil.set(JwtUtil.PREFIX_USER_TOKEN + sign, sign, JwtUtil.EXPIRE_TIME);
        ShiroUtil.getSession().setAttribute("currentUser", userEntity);
    
        return ResultBean.ok()
                         .put("userId", userEntity.getId())
                         .put("name", userEntity.getName())
                         .put("token", sign)
                         .put("expire", new Date(System.currentTimeMillis() + 60 * 24 * 60 * 1000));
    }
    
    /**
     * 分页查询用户信息
     *
     * @return UserEntity
     */
    @Override
    public IPage<UserEntity> getByPage(CustomPage<UserEntity> dataTable) {
        LambdaQueryWrapper<UserEntity> queryWrapper = Wrappers.<UserEntity>lambdaQuery()
                .ne(UserEntity::getStatus, StatusEnum.REMOVED.getCode());
        return page(dataTable, queryWrapper);
    }

    @Override
    @Cacheable(cacheNames = "user", key = "#loginName")
    public UserEntity selectByUserName(String loginName) {
        LambdaQueryWrapper<UserEntity> queryWrapper = Wrappers.<UserEntity>lambdaQuery().eq(UserEntity::getLoginName, loginName);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public UserVO getDetailById(Long userId) {
        UserEntity userEntity = baseMapper.selectById(userId);
        RoleEntity roleEntity = roleService.findById(userEntity.getRoleId());
        return userMapstruct.convert(userEntity, roleEntity);
    }

    @Override
    @CacheEvict(cacheNames = "user", allEntries = true)
    public boolean removeById(Serializable id) {
        UserEntity userEntity = getById(id);
        if (ObjectUtil.isNotEmpty(id) && 1L == userEntity.getRoleId()) {
            throw new GlobalException("不允许操作超级管理员用户");
        }
        return super.removeById(id);
    }

    @Override
    @CacheEvict(cacheNames = "user", allEntries = true)
    public boolean saveOrUpdate(UserEntity entity) {
        if (ObjectUtil.isNull(entity.getId())) {
            // 采用国密算法加密密码
            SymmetricCrypto sm4 = SmUtil.sm4(properties.sm4KeyBytes());
            String encryptHex = sm4.encryptHex(entity.getPassword());
            entity.setPassword(encryptHex);
        }
        return super.saveOrUpdate(entity);
    }
}
